package test.threads.queue.unstressed.impl;


import test.threads.queue.unstressed.IBoundedQueueFactory;
import test.threads.queue.unstressed.IQueue;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Queue implementation:
 * Circular array based
 * Concurrent (single-enq, single-deq)
 * Bounded
 * Blocking (by spin-wait)
 * <p/>
 *
 * @author cheremin
 * @since 21.09.11,  13:56
 */
public final class CABSESDQueue<T> extends AbstractSESDSequencer implements IQueue<T> {

    private final T[] elements;


    @SuppressWarnings( "unchecked" )
    public CABSESDQueue( final int size ) {
        super( size );
        elements = ( T[] ) new Object[size];
    }

    public void enqueue( final T item ) {
        final long newTail = nextTail();

        final int index = index( newTail - 1 );
        elements[index] = item;

        publishTail( newTail );
    }

    public T dequeue() {
        final long newHead = nextHead();

        final int index = index( newHead - 1 );
        final T item = elements[index];
        elements[index] = null;//for GC

        publishHead( newHead );
        return item;
    }

    private int index( final long sequence ) {
        return ( int ) ( sequence % length() );
    }

    @SuppressWarnings( "unchecked" )
    public static <T> IBoundedQueueFactory<T, CABSESDQueue<T>> factory() {
        return FACTORY;
    }

    public static final IBoundedQueueFactory FACTORY = new IBoundedQueueFactory<Object, CABSESDQueue<Object>>() {
        @Override
        public CABSESDQueue<Object> create( final int size ) {
            return new CABSESDQueue<Object>( size );
        }

        @Override
        public String toString() {
            return "CABSESDQueueFactory";
        }
    };

}
